package com.niuxuliang.activity.modules.process;

import com.niuxuliang.activity.common.R;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 流程管理
 *
 * @author xl.niu
 */
@Slf4j
@RestController
@RequestMapping("/process")
public class ProcessController {
    // 设计到的表
    // act_ge_bytearray  流程定义的文件
    // act_re_deployment 部署信息
    // act_re_procdef    流程定义的一些信息

    @Autowired
    private RepositoryService repositoryService;//管理流程定义
    @Autowired
    private RuntimeService runtimeService;

    /**
     * 部署流程
     *
     * @return
     */
    @RequestMapping("/deploy")
    public R deploy(String file, String processName) {
        //部署
        Deployment deployment = repositoryService.createDeployment().
                addClasspathResource("processes/" + file + ".bpmn")
//                .addClasspathResource("processes/flow.png")
                .name(processName)
                .deploy();
        //输出部署信息
        log.info("部署成功");
        return R.ok().put("data", deployment);
    }

    /**
     * 删除流程定义
     */
    @RequestMapping("/deleteProcess")
    public R deleteProcDeployment(String deploymentId, boolean fullDelete) {
        //找出部署的流程
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentName("新闻发布申请").singleResult();

        //，true:级联删除;false:非级联删除
        if (fullDelete) {
            repositoryService.deleteDeployment(deploymentId, true);//级联删除
        } else {
            repositoryService.deleteDeployment(deploymentId);//流程部署ID
        }
        return R.ok();
    }

    /**
     * 挂起或激活所有的流程实例
     */
    @RequestMapping("/suspendAllProcess/{key}")
    public R suspendAllProcess(@PathVariable("key") String key) {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(key)
                .list();

        ProcessDefinition processDefinition = list.get(0);
        boolean suspended = processDefinition.isSuspended();
        String processDefinitionId = processDefinition.getId();
        if (suspended) {
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, new Date());
            System.out.println("流程定义ID为：" + processDefinitionId + "已激活");
            return R.ok("流程定义ID为：" + processDefinitionId + "已激活");
        } else {
            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, new Date());
            System.out.println("流程定义ID为：" + processDefinitionId + "已挂起");
            return R.ok("流程定义ID为：" + processDefinitionId + "已挂起");
        }
    }

    /**
     * 挂起或激活单个的流程实例
     *
     * @param processDefinitionId
     * @return
     */
    @RequestMapping("/suspendSingleProcess/{processDefinitionId}")
    public R suspendSingleProcess(@PathVariable("processDefinitionId") String processDefinitionId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();

        boolean suspended = processInstance.isSuspended();
        String processInstanceId = processInstance.getProcessInstanceId();
        String id = processInstance.getId();
        if (suspended) {
            runtimeService.activateProcessInstanceById(processInstanceId);
            System.out.println("流程实例ID为：" + processInstanceId + "已激活");
            return R.ok("流程定义ID为：" + processDefinitionId + "已激活");
        } else {
            runtimeService.suspendProcessInstanceById(processInstanceId);
            System.out.println("流程实例ID为：" + processInstanceId + "已挂起");
            return R.ok("流程定义ID为：" + processDefinitionId + "已挂起");
        }
    }

    /**
     * 查询流程定义
     *
     * @param processDefinitionKey 流程key
     * @return
     */
    @RequestMapping("/query")
    public R query(String processDefinitionKey) {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        List<Map> res = new ArrayList<>();
        for (ProcessDefinition processDefinition : list) {
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("Id", processDefinition.getId());
            map.put("name", processDefinition.getName());
            map.put("key", processDefinition.getKey());
            map.put("deploymentId", processDefinition.getDeploymentId());
            map.put("version", processDefinition.getVersion());
            res.add(map);
        }
        return R.ok().put("data", res);
    }

    /**
     * 预览流程定义
     *
     * @param processDefinitionKey
     * @return
     */
    @RequestMapping("/preview")
    public R preview(String processDefinitionKey) {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        List<Map> res = new ArrayList<>();
        for (ProcessDefinition processDefinition : list) {
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("Id", processDefinition.getId());
            map.put("name", processDefinition.getName());
            map.put("key", processDefinition.getKey());
            map.put("deploymentId", processDefinition.getDeploymentId());
            map.put("version", processDefinition.getVersion());
            res.add(map);
        }
        return R.ok().put("data", res);
    }

}
